using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System.ComponentModel.DataAnnotations;
using System.Security.Claims;
using WeatherSystem.API.Models;
using WeatherSystem.API.Services;

namespace WeatherSystem.API.Controllers
{
    /// <summary>
    /// 认证控制器
    /// </summary>
    [ApiController]
    [Route("api/[controller]")]
    public class AuthController : ControllerBase
    {
        private readonly IAuthService _authService;
        private readonly ILogger<AuthController> _logger;

        public AuthController(
            IAuthService authService,
            ILogger<AuthController> logger)
        {
            _authService = authService;
            _logger = logger;
        }

        /// <summary>
        /// 用户登录
        /// </summary>
        [HttpPost("login")]
        [AllowAnonymous]
        public async Task<ActionResult<LoginResponse>> Login([FromBody] LoginRequest request)
        {
            try
            {
                if (!ModelState.IsValid)
                {
                    return BadRequest(new ApiErrorResponse
                    {
                        Message = "输入数据验证失败",
                        ValidationErrors = ModelState
                            .Where(x => x.Value?.Errors.Count > 0)
                            .ToDictionary(
                                kvp => kvp.Key,
                                kvp => kvp.Value?.Errors.Select(e => e.ErrorMessage).ToArray() ?? Array.Empty<string>()
                            ),
                        TraceId = HttpContext.TraceIdentifier
                    });
                }

                var ipAddress = GetClientIpAddress();
                var result = await _authService.LoginAsync(request, ipAddress);

                if (result == null)
                {
                    return Unauthorized(new ApiErrorResponse
                    {
                        Message = "用户名或密码错误，或账户已被锁定",
                        TraceId = HttpContext.TraceIdentifier
                    });
                }

                // 设置HttpOnly Cookie用于刷新令牌
                SetRefreshTokenCookie(result.RefreshToken);

                // 不在响应中返回刷新令牌（安全考虑）
                result.RefreshToken = string.Empty;

                return Ok(result);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "登录接口发生错误");
                return StatusCode(500, new ApiErrorResponse
                {
                    Message = "服务器内部错误",
                    TraceId = HttpContext.TraceIdentifier
                });
            }
        }

        /// <summary>
        /// 刷新访问令牌
        /// </summary>
        [HttpPost("refresh")]
        [AllowAnonymous]
        public async Task<ActionResult<TokenResponse>> RefreshToken([FromBody] RefreshTokenRequest? request = null)
        {
            try
            {
                // 从Cookie或请求体获取刷新令牌
                var refreshToken = request?.RefreshToken ?? GetRefreshTokenFromCookie();

                if (string.IsNullOrEmpty(refreshToken))
                {
                    return BadRequest(new ApiErrorResponse
                    {
                        Message = "刷新令牌不能为空",
                        TraceId = HttpContext.TraceIdentifier
                    });
                }

                var ipAddress = GetClientIpAddress();
                var result = await _authService.RefreshTokenAsync(refreshToken, ipAddress);

                if (result == null)
                {
                    return Unauthorized(new ApiErrorResponse
                    {
                        Message = "刷新令牌无效或已过期",
                        TraceId = HttpContext.TraceIdentifier
                    });
                }

                // 更新Cookie中的刷新令牌
                SetRefreshTokenCookie(result.RefreshToken);

                // 不在响应中返回刷新令牌
                result.RefreshToken = string.Empty;

                return Ok(result);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "刷新令牌接口发生错误");
                return StatusCode(500, new ApiErrorResponse
                {
                    Message = "服务器内部错误",
                    TraceId = HttpContext.TraceIdentifier
                });
            }
        }

        /// <summary>
        /// 用户注册
        /// </summary>
        [HttpPost("register")]
        [AllowAnonymous]
        public async Task<ActionResult> Register([FromBody] RegisterRequest request)
        {
            try
            {
                if (!ModelState.IsValid)
                {
                    return BadRequest(new ApiErrorResponse
                    {
                        Message = "输入数据验证失败",
                        ValidationErrors = ModelState
                            .Where(x => x.Value?.Errors.Count > 0)
                            .ToDictionary(
                                kvp => kvp.Key,
                                kvp => kvp.Value?.Errors.Select(e => e.ErrorMessage).ToArray() ?? Array.Empty<string>()
                            ),
                        TraceId = HttpContext.TraceIdentifier
                    });
                }

                var result = await _authService.RegisterAsync(request);

                if (!result)
                {
                    return BadRequest(new ApiErrorResponse
                    {
                        Message = "用户名或邮箱已存在",
                        TraceId = HttpContext.TraceIdentifier
                    });
                }

                return Ok(new { message = "注册成功" });
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "注册接口发生错误");
                return StatusCode(500, new ApiErrorResponse
                {
                    Message = "服务器内部错误",
                    TraceId = HttpContext.TraceIdentifier
                });
            }
        }

        /// <summary>
        /// 用户登出
        /// </summary>
        [HttpPost("logout")]
        [Authorize]
        public async Task<ActionResult> Logout()
        {
            try
            {
                var refreshToken = GetRefreshTokenFromCookie();
                if (!string.IsNullOrEmpty(refreshToken))
                {
                    var ipAddress = GetClientIpAddress();
                    await _authService.RevokeTokenAsync(refreshToken, ipAddress);
                }

                // 清除Cookie
                ClearRefreshTokenCookie();

                return Ok(new { message = "登出成功" });
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "登出接口发生错误");
                return StatusCode(500, new ApiErrorResponse
                {
                    Message = "服务器内部错误",
                    TraceId = HttpContext.TraceIdentifier
                });
            }
        }

        /// <summary>
        /// 更改密码
        /// </summary>
        [HttpPost("change-password")]
        [Authorize]
        public async Task<ActionResult> ChangePassword([FromBody] ChangePasswordRequest request)
        {
            try
            {
                if (!ModelState.IsValid)
                {
                    return BadRequest(new ApiErrorResponse
                    {
                        Message = "输入数据验证失败",
                        ValidationErrors = ModelState
                            .Where(x => x.Value?.Errors.Count > 0)
                            .ToDictionary(
                                kvp => kvp.Key,
                                kvp => kvp.Value?.Errors.Select(e => e.ErrorMessage).ToArray() ?? Array.Empty<string>()
                            ),
                        TraceId = HttpContext.TraceIdentifier
                    });
                }

                var userId = GetCurrentUserId();
                if (userId == null)
                {
                    return Unauthorized(new ApiErrorResponse
                    {
                        Message = "用户身份验证失败",
                        TraceId = HttpContext.TraceIdentifier
                    });
                }

                var result = await _authService.ChangePasswordAsync(userId.Value, request);

                if (!result)
                {
                    return BadRequest(new ApiErrorResponse
                    {
                        Message = "当前密码错误",
                        TraceId = HttpContext.TraceIdentifier
                    });
                }

                return Ok(new { message = "密码更改成功" });
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "更改密码接口发生错误");
                return StatusCode(500, new ApiErrorResponse
                {
                    Message = "服务器内部错误",
                    TraceId = HttpContext.TraceIdentifier
                });
            }
        }

        /// <summary>
        /// 获取当前用户信息
        /// </summary>
        [HttpGet("me")]
        [Authorize]
        public async Task<ActionResult<UserInfo>> GetCurrentUser()
        {
            try
            {
                var userId = GetCurrentUserId();
                if (userId == null)
                {
                    return Unauthorized(new ApiErrorResponse
                    {
                        Message = "用户身份验证失败",
                        TraceId = HttpContext.TraceIdentifier
                    });
                }

                var userInfo = await _authService.GetUserInfoAsync(userId.Value);
                if (userInfo == null)
                {
                    return NotFound(new ApiErrorResponse
                    {
                        Message = "用户不存在",
                        TraceId = HttpContext.TraceIdentifier
                    });
                }

                return Ok(userInfo);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "获取当前用户信息发生错误");
                return StatusCode(500, new ApiErrorResponse
                {
                    Message = "服务器内部错误",
                    TraceId = HttpContext.TraceIdentifier
                });
            }
        }

        /// <summary>
        /// 撤销所有刷新令牌（用于安全登出）
        /// </summary>
        [HttpPost("revoke-all")]
        [Authorize]
        public async Task<ActionResult> RevokeAllTokens()
        {
            try
            {
                var userId = GetCurrentUserId();
                if (userId == null)
                {
                    return Unauthorized();
                }

                await _authService.RevokeAllTokensAsync(userId.Value);
                ClearRefreshTokenCookie();

                return Ok(new { message = "所有会话已终止" });
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "撤销所有令牌接口发生错误");
                return StatusCode(500, new ApiErrorResponse
                {
                    Message = "服务器内部错误",
                    TraceId = HttpContext.TraceIdentifier
                });
            }
        }

        #region Helper Methods

        /// <summary>
        /// 获取当前用户ID
        /// </summary>
        private Guid? GetCurrentUserId()
        {
            var userIdClaim = User?.FindFirst("userId") ?? User?.FindFirst(ClaimTypes.NameIdentifier);
            return userIdClaim != null && Guid.TryParse(userIdClaim.Value, out var userId) ? userId : null;
        }

        /// <summary>
        /// 获取客户端IP地址
        /// </summary>
        private string GetClientIpAddress()
        {
            var forwarded = HttpContext.Request.Headers["X-Forwarded-For"].FirstOrDefault();
            if (!string.IsNullOrEmpty(forwarded))
            {
                return forwarded.Split(',')[0].Trim();
            }

            var realIp = HttpContext.Request.Headers["X-Real-IP"].FirstOrDefault();
            if (!string.IsNullOrEmpty(realIp))
            {
                return realIp;
            }

            return HttpContext.Connection.RemoteIpAddress?.ToString() ?? "unknown";
        }

        /// <summary>
        /// 设置刷新令牌Cookie
        /// </summary>
        private void SetRefreshTokenCookie(string refreshToken)
        {
            var cookieOptions = new CookieOptions
            {
                HttpOnly = true,
                Secure = true, // HTTPS required
                SameSite = SameSiteMode.Strict,
                Expires = DateTime.UtcNow.AddDays(7),
                Path = "/api/auth"
            };

            Response.Cookies.Append("refreshToken", refreshToken, cookieOptions);
        }

        /// <summary>
        /// 从Cookie获取刷新令牌
        /// </summary>
        private string? GetRefreshTokenFromCookie()
        {
            return Request.Cookies["refreshToken"];
        }

        /// <summary>
        /// 清除刷新令牌Cookie
        /// </summary>
        private void ClearRefreshTokenCookie()
        {
            Response.Cookies.Delete("refreshToken", new CookieOptions
            {
                HttpOnly = true,
                Secure = true,
                SameSite = SameSiteMode.Strict,
                Path = "/api/auth"
            });
        }

        #endregion
    }
}